package com.zc.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zc.dto.ClassExamStatsDTO;
import com.zc.exception.CustomerException;
import com.zc.mapper.ExamsMapper;
import com.zc.mapper.ScoreStatsMapper;
import com.zc.pojo.Exams;
import com.zc.pojo.Scores;
import com.zc.service.ExamStatisticsService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ExamStatisticsServiceImpl extends ServiceImpl<ScoreStatsMapper, Scores> implements ExamStatisticsService {

    @Resource
    public ScoreStatsMapper scoreStatsMapper;

    @Resource
    public ExamsMapper examsMapper;

    /**
     * 获取指定考试的班级统计数据（优化：空值处理、日志监控、效率提升）
     */
    @Override
    public List<ClassExamStatsDTO> getClassStatsForExam(Integer examId,
                                                        Integer specifiedScore,
                                                        Integer excellentScore,
                                                        Integer passScore) {
        long startTime = System.currentTimeMillis();
        // 1. 参数校验（防止无效查询）
        if (examId == null || examId <= 0) {
            throw new CustomerException("查询失败：考试ID无效（examId={}）" + examId);
        }
        // 新增：检查考试是否存在
        Exams exam = examsMapper.selectById(examId);// 需要新增mapper方法
        if (exam == null) {
            throw new CustomerException("考试不存在：examId={}" + examId);
        }
        log.info("开始查询考试{}的班级统计", examId);
        // 2. 设置默认值（优化：使用orElseGet延迟计算）
        int specified = Optional.ofNullable(specifiedScore).orElse(0);
        int excellent = Optional.ofNullable(excellentScore).orElse(96);
        int pass = Optional.ofNullable(passScore).orElse(72);


        // 3. 查询基础统计数据
        List<Map<String, Object>> basicStats = scoreStatsMapper.getClassBasicStats(examId);
        log.info("查询基础统计耗时：{}ms", System.currentTimeMillis() - startTime);
        if (basicStats.isEmpty()) {
            throw new CustomerException("未查询到" + examId + "班级基础数据");
        }

        // 4. 初始化DTO列表（优化：严格空值处理）
        Map<String, ClassExamStatsDTO> classStatsMap = basicStats.stream()
                .map(stats -> {
                    ClassExamStatsDTO dto = new ClassExamStatsDTO();
                    // 班级名称（非空处理）
                    dto.setClassName(Optional.ofNullable((String) stats.get("classname"))
                            .filter(className -> !className.trim().isEmpty()) // 过滤空字符串
                            .orElse("未知班级"));
                    // 总人数（默认0）
                    // 修正总人数读取（键名改为totalstudents）
                    dto.setTotalStudents(Optional.ofNullable((Number) stats.get("totalstudents"))
                            .map(Number::intValue).orElse(0));

                    // 修正平均分读取（键名改为averagescore）
                    dto.setAverageScore(convertToBigDecimal(stats.get("averagescore"), BigDecimal.ZERO));
                    // 最高分/最低分（允许null）
                    // 最高分/最低分（允许null）
                    dto.setMaxScore(convertToBigDecimal(stats.get("maxscore"), null));  // 键名改为maxscore
                    dto.setMinScore(convertToBigDecimal(stats.get("minscore"), null));  // 键名改为minscore
                    // 初始化积分
                    dto.setTotalPoints(0);
                    return dto;
                })
                .collect(Collectors.toMap(
                        ClassExamStatsDTO::getClassName,
                        dto -> dto,
                        (existing, replacement) -> {
                            log.warn("发现重复班级名称：{}（已自动合并）", existing.getClassName());
                            return existing;
                        }
                ));

        // 5. 查询基础统计数据
        long queryScoresStart = System.currentTimeMillis();
        List<Map<String, Object>> studentScores = scoreStatsMapper.getStudentScoresByExam(examId);
        log.info("查询学生成绩耗时：{}ms，数据量：{}条", System.currentTimeMillis() - queryScoresStart, studentScores.size());
        // 计算高级统计
        long calculateStart = System.currentTimeMillis();
        calculateAdvancedStats(studentScores, classStatsMap, specified, excellent, pass);
        log.info("计算高级统计耗时：{}ms", System.currentTimeMillis() - calculateStart);

        // 6. 计算排名（优化：处理空列表情况）
        List<ClassExamStatsDTO> resultList = new ArrayList<>(classStatsMap.values());
        if (resultList.isEmpty()) {
            return Collections.emptyList();
        }

        // 按积分降序排序（同分同名次）
        resultList.sort((a, b) -> b.getTotalPoints().compareTo(a.getTotalPoints()));
        int currentRank = 1;
        for (int i = 0; i < resultList.size(); i++) {
            ClassExamStatsDTO dto = resultList.get(i);
            if (i > 0 && !dto.getTotalPoints().equals(resultList.get(i - 1).getTotalPoints())) {
                currentRank = i + 1; // 积分不同时更新排名
            }
            dto.setRank(currentRank);
        }
        return resultList;
    }

    /**
     * 计算高级统计指标（优化：减少循环内判断）
     */
    public void calculateAdvancedStats(List<Map<String, Object>> studentScores,
                                       Map<String, ClassExamStatsDTO> classStatsMap,
                                       int specifiedScore,
                                       int excellentScore,
                                       int passScore) {
        for (Map<String, Object> student : studentScores) {
            // 班级名称（跳过无效班级）
            String className = (String) student.get("classname");
            ClassExamStatsDTO classDTO = classStatsMap.get(className);
            if (classDTO == null) {
                continue;
            }

            // 成绩（已在SQL中过滤0分和null，直接转换）
            BigDecimal score = convertToBigDecimal(student.get("score"), null);
            if (score == null) {
                continue; // 理论上不会走到这里，双重保险
            }
            double numericScore = score.doubleValue();

            // 计算积分和分数段（提取为独立方法，提高可读性）
            calculatePointsAndSegments(classDTO, numericScore);

            // 统计自定义分数段人数（合并判断条件）
            if (numericScore > specifiedScore) {
                classDTO.setOverSpecifiedScoreCount(classDTO.getOverSpecifiedScoreCount() + 1);
            }
            if (numericScore >= excellentScore) {
                classDTO.setExcellentCount(classDTO.getExcellentCount() + 1);
            }
            if (numericScore >= passScore) {
                classDTO.setPassCount(classDTO.getPassCount() + 1);
            }
        }

        // 计算比率（优化：避免除以0）
        classStatsMap.values().forEach(dto -> {
            int total = dto.getTotalStudents();
            if (total <= 0) {
                dto.setExcellentRate(BigDecimal.ZERO);
                dto.setPassRate(BigDecimal.ZERO);
                return;
            }
            dto.setExcellentRate(calculateRate(dto.getExcellentCount(), total));
            dto.setPassRate(calculateRate(dto.getPassCount(), total));
        });
    }

    /**
     * 计算积分和分数段分布（优化：边界值处理）
     */
    public void calculatePointsAndSegments(ClassExamStatsDTO classDTO, double numericScore) {
        // 处理120分特殊情况
        if (numericScore == 120) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 15);
            classDTO.getSegmentCounts().put("120", classDTO.getSegmentCounts().get("120") + 1);
            return;
        }

        // 按分数段区间计算（优化：使用if-else if短路特性）
        if (numericScore >= 114) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 14);
            classDTO.getSegmentCounts().put("[114,120)", classDTO.getSegmentCounts().get("[114,120)") + 1);
        } else if (numericScore >= 108) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 12);
            classDTO.getSegmentCounts().put("[108,114)", classDTO.getSegmentCounts().get("[108,114)") + 1);
        } else if (numericScore >= 102) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 10);
            classDTO.getSegmentCounts().put("[102,108)", classDTO.getSegmentCounts().get("[102,108)") + 1);
        } else if (numericScore >= 96) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 8);
            classDTO.getSegmentCounts().put("[96,102)", classDTO.getSegmentCounts().get("[96,102)") + 1);
        } else if (numericScore >= 84) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 6);
            classDTO.getSegmentCounts().put("[84,96)", classDTO.getSegmentCounts().get("[84,96)") + 1);
        } else if (numericScore >= 72) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 4);
            classDTO.getSegmentCounts().put("[72,84)", classDTO.getSegmentCounts().get("[72,84)") + 1);
        } else if (numericScore >= 60) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 2);
            classDTO.getSegmentCounts().put("[60,72)", classDTO.getSegmentCounts().get("[60,72)") + 1);
        } else if (numericScore >= 48) {
            classDTO.setTotalPoints(classDTO.getTotalPoints() + 1);
            classDTO.getSegmentCounts().put("[48,60)", classDTO.getSegmentCounts().get("[48,60)") + 1);
        } else if (numericScore >= 0) {
            classDTO.getSegmentCounts().put("[0,48)", classDTO.getSegmentCounts().get("[0,48)") + 1);
        }
    }

    /**
     * 计算比率（优化：精确处理）
     */
    public BigDecimal calculateRate(int count, int total) {
        if (count <= 0 || total <= 0) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(count)
                .divide(new BigDecimal(total), 4, RoundingMode.HALF_UP) // 先保留4位小数
                .multiply(new BigDecimal(100)) // 转换为百分比
                .setScale(2, RoundingMode.HALF_UP); // 最终保留2位小数
    }


    /**
     * 转换为BigDecimal（优化：增加默认值参数）
     */
    public BigDecimal convertToBigDecimal(Object value, BigDecimal defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        if (value instanceof Number) {
            return new BigDecimal(((Number) value).toString());
        }
        return defaultValue;
    }

    public BigDecimal convertToBigDecimal(Object value) {
        if (value == null) {
            return null;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        // 处理数字类型（Double、Long、Integer等）
        if (value instanceof Number) {
            return new BigDecimal(((Number) value).toString());
        }
        // 处理字符串类型的数字（如"98.5"）
        if (value instanceof String) {
            try {
                return new BigDecimal((String) value);
            } catch (NumberFormatException e) {
                // 非数字字符串返回null（根据业务场景决定是否抛异常）
                return null;
            }
        }
        return null;
    }
}
